<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<title>PlayIntegrity PIF Selector</title>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<style>
:root{
  --bg:#1f2233; --fg:#e6e6e6; --accent:#1592FF;
  --panel-bg:#232637D9; --shadow:rgba(0,0,0,0.55);
  --radius:16px; --transition:0.25s;
  --active:var(--accent);
}
*{box-sizing:border-box}
body{
  margin:0;min-height:100vh;display:flex;align-items:center;justify-content:center;
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,system-ui;
  background:linear-gradient(135deg,#1c1e2b,#10121c);
  color:var(--fg);padding:22px;-webkit-font-smoothing:antialiased;
}
.container{width:440px;max-width:96%;}
.card{
  background:var(--panel-bg);border-radius:var(--radius);padding:22px;
  box-shadow:0 16px 48px var(--shadow);position:relative;overflow:hidden;
}
.card::before{
  content:"";position:absolute;inset:0;
  background:radial-gradient(circle,var(--accent) 0%,transparent 70%);
  opacity:.1;filter:blur(14px);pointer-events:none;
}
h1{
  margin:0 0 16px;text-align:center;font-size:20px;
  color:var(--accent);font-weight:600;letter-spacing:.3px;
}
.rows{display:grid;gap:10px;margin-top:14px;position:relative;z-index:2;}
.item{
  display:flex;align-items:center;justify-content:space-between;
  padding:16px;border-radius:var(--radius);
  background:rgba(255,255,255,0.03);
  border:1px solid rgba(255,255,255,0.08);
  cursor:pointer;transition:transform var(--transition),box-shadow var(--transition),background var(--transition),border var(--transition);
}
.item:hover{
  transform:translateY(-4px);
  background:rgba(255,255,255,0.05);
  box-shadow:0 10px 28px rgba(0,0,0,0.5);
}
.item.active{
  border:2px solid var(--accent);
  background:rgba(21,146,255,0.12);
}
.item:active{transform:scale(0.98);}
.left{flex-shrink:0;width:60px;text-align:center;}
.badge{display:inline-block;padding:7px 10px;border-radius:10px;background:rgba(255,255,255,0.05);font-size:13px;font-weight:600;}
.info{flex:1;overflow:hidden;}
.line{display:flex;justify-content:space-between;align-items:center;gap:8px;}
.meta{margin-top:6px;display:flex;flex-wrap:wrap;gap:8px;font-size:12px;color:rgba(255,255,255,0.65);}
.expiry{font-weight:700;color:var(--accent);}
.small{font-size:12px;color:rgba(255,255,255,0.55);}
.empty{
  text-align:center;color:rgba(255,255,255,0.4);
  padding:22px;border-radius:10px;background:rgba(255,255,255,0.03);
}
.footer{text-align:center;margin-top:12px;font-size:12px;color:rgba(255,255,255,0.45);}

.refresh-btn{
  margin-top:10px;text-align:center;
  font-size:13px;cursor:pointer;color:var(--accent);
  opacity:.75;transition:.2s;
}
.refresh-btn:hover{opacity:1;}

.expiry-badge {
  padding: 4px 10px;
  border-radius: 8px;
  font-weight: 600;
  font-size: 12px;
  white-space: nowrap;
  display: inline-block;
}

.expired {
  background: rgba(255, 0, 0, 0.25);
  color: #ff6b6b;
  border: 1px solid rgba(255, 0, 0, 0.4);
}

.expiring-soon {
  background: rgba(255,165,0,0.25);
  color: #ffb85c;
  border: 1px solid rgba(255,165,0,0.45);
}

.safe-expiry {
  background: rgba(27, 205, 0, 0.18);
  color: #1BCD00;
  border: 1px solid rgba(27, 205, 0, 0.18);
}
</style>
</head>
<body>

<div class="container">
  <div class="card">
    <h1><span class="material-icons" style="vertical-align:middle;font-size:19px;margin-right:6px;">settings</span> Play Integrity Prop Selector</h1>

    <div id="rows" class="rows" aria-live="polite">
      <div class="empty">Scanning for <code>*custom.pif.prop</code> …</div>
    </div>

    <div class="refresh-btn" onclick="forceRefresh()">
      <span class="material-icons" style="font-size:16px;vertical-align:middle;">refresh</span>
      Refresh List
    </div>

    <div class="footer">IntegrityBox • 2025</div>
  </div>
</div>

<script>
function popup(msg){
  try{
    if(window.toast) return window.toast(String(msg));
    if(window.kernelsu?.toast) return window.kernelsu.toast(String(msg));
    if(window.ksu?.toast) return window.ksu.toast(String(msg));
  }catch{}
}

const CACHE_KEY = "pif_cache_v1";
const CACHE_TIME = 24*60*60*1000; // 24h

const SEARCH_DIR='/data/adb/modules/playintegrity/toolbox';
const DEST='/data/adb/modules/playintegrityfix/custom.pif.prop';
const rows=document.getElementById("rows");

async function sh(cmd){
  try{
    if(typeof ksu?.exec==="function"){
      const out = ksu.exec(cmd);
      if(out?.then) return (await out).toString().trim();
      if(typeof out==="string") return out.trim();
      return await new Promise(res=>{
        const cb="cb_"+Date.now()+"_"+(Math.random()*10000|0);
        window[cb]=(c,o,e)=>{delete window[cb];res((o||"")+(e||""));};
        ksu.exec(cmd,"{}",cb);
      });
    }
  }catch(e){}
  return "";
}

async function readKV(file,key){
  return(await sh(`sh -c 'grep -m1 "^${key}=" "${file}" | cut -d"=" -f2- || true'`)).trim();
}
async function readExpiry(file){
  return(await sh(`sh -c 'grep -m1 "^# *Estimated Expiry:" "${file}" | sed "s/^# *Estimated Expiry:[[:space:]]*//" || true'`)).trim();
}
async function findCandidates(){
  const out=await sh(`sh -c 'find "${SEARCH_DIR}" -maxdepth 1 -type f -name "*custom.pif.prop" -print0 | sort -z'`);
  if(!out) return [];
  return out.split("\0").filter(Boolean).map(x=>x.trim());
}

function buildUI(metaList){
  rows.innerHTML="";
  const frag=document.createDocumentFragment();
  metaList.forEach((item,i)=>{
    frag.appendChild(makeItem(i,item.file,item.meta));
  });
  rows.appendChild(frag);
}

function makeItem(index,file,meta){
  const div=document.createElement("div");
  div.className="item";
  div.dataset.file=file;

  const left=document.createElement("div");
  left.className="left";
  left.innerHTML=`<div class="badge">#${index+1}</div>`;

  const info=document.createElement("div");
  info.className="info";

  const line=document.createElement("div");
  line.className="line";
  line.innerHTML=`
    <div><strong>${meta.MODEL||"Unknown Model"}</strong><div class="small">${meta.DEVICE||"unknown"}</div></div>
    <div class="small">${meta.RELEASE?("Android "+meta.RELEASE):""}</div>
  `;

  const metaRow=document.createElement("div");
  metaRow.className="meta";
  metaRow.innerHTML=`
    <div>FP: ${meta.FINGERPRINT?meta.FINGERPRINT.substring(0,34)+"…":"—"}</div>
    <div>Patch: ${meta.SECURITY_PATCH||"—"}</div>
    <div class="expiry" data-exp="${meta.ESTIMATED || ''}"></div>
  `;

  info.append(line,metaRow);
  div.append(left,info);

  div.onclick=async()=>{
    document.querySelectorAll(".item").forEach(x=>x.classList.remove("active"));
    div.classList.add("active");

    await sh(`cp -f "${file}" "${DEST}" && chmod 0644 "${DEST}"`);
    await sh(`am force-stop com.google.android.gms.unstable 2>/dev/null || true;
              am force-stop com.google.android.gms 2>/dev/null || true;
              am force-stop com.android.vending 2>/dev/null || true`);
    popup("Prop applied & GMS restarted");
  };
  
  setTimeout(() => {
    const expEl = div.querySelector('.expiry');
    if (expEl) {
      formatExpiry(expEl, expEl.dataset.exp);
    }
  }, 10);

  return div;
}

async function scanAndCache(){
  const files=await findCandidates();
  const metaList=[];

  for(const f of files){
    const [MODEL,DEVICE,RELEASE,SECURITY_PATCH,FINGERPRINT,ESTIMATED] = await Promise.all([
      readKV(f,"MODEL"),
      readKV(f,"DEVICE"),
      readKV(f,"RELEASE"),
      readKV(f,"SECURITY_PATCH"),
      readKV(f,"FINGERPRINT"),
      readExpiry(f)
    ]);
    metaList.push({file:f,meta:{MODEL,DEVICE,RELEASE,SECURITY_PATCH,FINGERPRINT,ESTIMATED}});
  }

  localStorage.setItem(CACHE_KEY,JSON.stringify({
    time:Date.now(),
    data:metaList
  }));

  return metaList;
}

function loadFromCache(){
  const raw=localStorage.getItem(CACHE_KEY);
  if(!raw) return null;
  try{
    const obj=JSON.parse(raw);
    if(Date.now()-obj.time > CACHE_TIME) return null;
    return obj.data;
  }catch{
    return null;
  }
}

function formatExpiry(el, dateStr) {
  if (!dateStr || !dateStr.trim()) {
    el.innerHTML = `<span class="expiry-badge safe-expiry">IDK Bro 😭🙏💔🥀</span>`;
    return;
  }

  const expDate = new Date(dateStr);
  if (isNaN(expDate)) {
    el.innerHTML = `<span class="expiry-badge safe-expiry">${dateStr}</span>`;
    return;
  }

  const now = new Date();
  const diffMs = expDate - now;
  const diffDays = Math.floor(diffMs / (1000*60*60*24));

  if (diffDays < 0) {
    el.innerHTML = `<span class="expiry-badge expired">Banned ${Math.abs(diffDays)} days ago</span>`;
    return;
  }

  if (diffDays <= 7) {
    el.innerHTML = `<span class="expiry-badge expiring-soon">Expiring in ${diffDays} days</span>`;
    return;
  }

  el.innerHTML = `<span class="expiry-badge safe-expiry">Expires in ${diffDays} days</span>`;
}

async function init(){
  const cache=loadFromCache();
  if(cache){
    buildUI(cache);
    return;
  }

  rows.innerHTML=`<div class="empty">Scanning… ⏳</div>`;
  const fresh=await scanAndCache();
  buildUI(fresh);
}

async function forceRefresh(){
  rows.innerHTML=`<div class="empty">Refreshing… ⏳</div>`;
  const fresh=await scanAndCache();
  buildUI(fresh);
  popup("List refreshed");
}

document.addEventListener("DOMContentLoaded",init);
</script>

</body>
</html>